package com.km.core.utils;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.km.core.dto.BaseDto;
import com.km.core.dto.LogResult;
import com.km.core.intercepter.RetryInterceptor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.UUID;

import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * <p>OkHttp请求封转</p>
 * Created by zhezhiyong@163.com on 2017/4/27.
 */
@Slf4j
@SuppressWarnings("unused")
public class OKHttp {

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final MediaType MEDIA_TYPE_JPG = MediaType.parse("image/jpeg");
    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    private static final String IMGUR_CLIENT_ID = "...";
    private static OkHttpClient client;

    static {
        client = new OkHttpClient.Builder()
                //防止302重定向死循环
                .followRedirects(false)
                .followSslRedirects(false)
                //重试3次
                .addInterceptor(new RetryInterceptor(2))
//                .addInterceptor(new NetInterceptor())
                .connectTimeout(10, SECONDS)
                .writeTimeout(3, SECONDS)
                .readTimeout(3, SECONDS)
                .build();
    }

    public static String postForm(String url, BaseDto dto) {
        LogResult logResult = new LogResult();
        logResult.setStart(new Date());
        logResult.setUrl(url);
        logResult.setParameter(dto.toJsonFilter());
        FormBody.Builder builder = new FormBody.Builder();
        for (String key : dto.keySet()) {
            builder.add(key, dto.getAsString(key, ""));
        }
        RequestBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)
                .post(formBody)
                .build();
        RequestBody body = request.body();
        Call call = client.newCall(request);
        String result;
        result = sendPost(call);
        logResult.setResponse(result);
        log.info(logResult.toString());
        return result;
    }

    public static String post(String url, JSONObject obj) {
        LogResult logResult = new LogResult();
        logResult.setStart(new Date());
        logResult.setUrl(url);
        logResult.setParameter(obj.toJSONString());
        String result;
        RequestBody body = RequestBody.create(JSON, obj.toJSONString());
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Call call = client.newCall(request);
        result = sendPost(call);
        logResult.setResponse(result);
        log.info(logResult.toString());
        return result;
    }

    public static String post(String url, String json) {
        LogResult logResult = new LogResult();
        logResult.setStart(new Date());
        logResult.setUrl(url);
        logResult.setParameter(json);
        String result;
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Call call = client.newCall(request);
        result = sendPost(call);
        logResult.setResponse(result);
        log.info(logResult.toString());
        return result;
    }

    private static String sendPost(Call call) {
        String result = null;
        try {
            Response response = call.execute();
            result = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("http fail: {}", e);
        }
        return result;
    }

    public static String get(String url) {
        LogResult logResult = new LogResult();
        logResult.setStart(new Date());
        logResult.setUrl(url);
        String result = null;
        Request request = new Request.Builder()
                .url(url)
                .build();
        try (Response response = client.newCall(request).execute()) {
            result = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("http fail: {}", e);
        }
        logResult.setResponse(result);
        log.info(logResult.toString());
        return result;
    }

    public static void downloadFile(String url, String fileName) {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response;
        try {
            OkHttpClient newClient = client.newBuilder()
                    .followRedirects(true)
                    .followSslRedirects(true)
                    .build();
            response = newClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("http fail: {}", e);
            return;
        }
        if (!response.isSuccessful()) {
            log.error("downloadFile=" + url + "|| Http Status=:" + response.code());
            return;
        }
        if (Strings.isNullOrEmpty(fileName)) {
//            fileName = Tools.getFileNameByHeader(response.header("Content-Disposition"));
            fileName = UUID.randomUUID().toString();
        }
        String filePath = PathUtils.GetProjectTempPath() + fileName;
        File file = new File(filePath);
        try (InputStream in = response.body().byteStream(); FileOutputStream fos = new FileOutputStream(file)) {
            byte[] buf = new byte[2048];
            int len;
            while ((len = in.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("file read save error: {}", e);
        }
    }

    public static void uploadFile(String url, BaseDto dto, String picPath) {
        Path path = Paths.get(picPath);
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        for (String key : dto.keySet()) {
            builder.addFormDataPart(key, dto.getAsString(key));
        }
//        RequestBody requestBody = new MultipartBody.Builder()
//                .setType(MultipartBody.FORM)
//                .addFormDataPart("title", "Square Logo")
//                .addFormDataPart("image", "logo-square.png",
//                        RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))\
//                .build();
        RequestBody requestBody = builder.build();
        Request request = new Request.Builder()
                .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
                .url("https://api.imgur.com/3/image")
                .post(requestBody)
                .build();
        try (Response response = client.newCall(request).execute();) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            System.out.println(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
            log.error("file upload error: {}", e);
        }
    }

    public static void main(String[] args) {
        downloadFile("http://wx.qlogo.cn/mmopen/9CdzqzR0kicnXp1lDQV1q4y2SBjWjom2nBsY5sSbBQymvQ8tkzLRDl7lacKnzfmqp0LibbcbZN8WvbDpdHmBkBtzdMHXoicrCm9/0.jpg", null);
    }

    public static String post(String url, BaseDto dto) {
        LogResult logResult = new LogResult();
        logResult.setStart(new Date());
        logResult.setUrl(url);
        logResult.setParameter(dto.toJsonFilter());
        String result;
        RequestBody body = RequestBody.create(JSON, dto.toJson());
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Call call = client.newCall(request);
        result = sendPost(call);
        logResult.setResponse(result);
        log.info(logResult.toString());
        return result;
    }
}
